import {
  ArgumentsHost,
  BadRequestException,
  Catch,
  ExceptionFilter,
  HttpException,
  HttpStatus,
  Inject,
} from '@nestjs/common';
import { Dayjs } from '@shencom/utils-date';
import { FastifyReply, FastifyRequest } from 'fastify';

import { LoggerService } from '../logger/logger.service';
import { getReqMainInfo } from '../middleware/utils';
import { BusinessException } from './business.exception';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  constructor(@Inject(LoggerService) private readonly logger: LoggerService) {}

  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<FastifyReply>();
    const request = ctx.getRequest<FastifyRequest>();
    const status = exception.getStatus();
    // 处理业务异常
    const error = exception.getResponse() as any;

    const msg =
      (Array.isArray(error?.message) && error?.message?.[0]) ||
      exception.message ||
      (status >= 500 ? 'Service Error' : 'Client Error');

    const req = getReqMainInfo(request);

    this.logger.error(msg, { req, stack: exception.stack });

    if (exception instanceof BusinessException) {
      response.status(HttpStatus.OK).send({
        errcode: error['errcode'] || '5000',
        errmsg: error['errmsg'] || msg,
      });
      return;
    }

    if (exception instanceof BadRequestException) {
      response.status(HttpStatus.INTERNAL_SERVER_ERROR).send({
        errcode: '5000',
        errmsg: msg,
      });
      return;
    }

    response.status(status).send({
      ...error,
      status,
      timestamp: Dayjs().toISOString(),
      path: request.url,
      message: msg,
    });
  }
}
